// 是否为对象
export function isObject(data) {
    return typeof data == 'object' && data != null;
}

export function isArray(data) {
    return Object.prototype.toString.call(data) == '[object Array]'
}

export function isString(data) {
    return Object.prototype.toString.call(data) == '[object String]'
}

export function isFunction(data) {
    return Object.prototype.toString.call(data) == '[object Function]'
}

// 对数据进行 响应式
export function def(obj, key, value, enumerable) {
    Object.defineProperty(obj, key, {
        enumerable: !!enumerable,
        configurable: true,
        value
    })
}

// "数据 代理"          vue    _data  name
export function proxy(target, obj, key) {
    // 利用 闭包 存一个 中间值（_data）， 后期访问 vue.name 就相当于 直接 访问 vue._data.name， 设置值也是一样
    Object.defineProperty(target, key, {
        configurable: true,
        enumerable: true,
        set(newVal) {
            target[obj][key] = newVal
        },
        get() {
            // 直接返回  vue._data.属性
            return target[obj][key]
        }
    })
}


// 替换为驼峰 font-size 转换为 fontSize
const camelizeRE = /-(\w)/g;
export function camelize(str) {
    return str.replace(camelizeRE, function (_, c) {
        return c ? c.toUpperCase() : ''
    })
};

// 生命周期
const LIFECIRCLE_HOOKS = [
    'beforeCreate',
    'created',
    'beforeMount',
    'mounted',
    'beforeUpdate',
    'updated',
    'beforeDestroy',
    'destroyed'
]

const starts = {}
starts.data = function (parentVal, childVal) {
    return childVal
}

//合并生命周期
function mergeHook(parentVal, childVal) {
    /*     如果有 子value 并且有父value 就让它与 父value 合并成数组返回
        如果没有 父value 就应该将 子value 返回成数组， 
        如果没有 子value 就直接返回 父value（是个数组） */

    if (childVal) {
        if (parentVal) {
            return parentVal.concat(childVal)
        } else {
            return [childVal]
        }
    } else {
        return parentVal
    }
}
// 筛选 生命周期函数
LIFECIRCLE_HOOKS.forEach(hook => {
    starts[hook] = mergeHook
})


// 合并数据  global-api文件用到
export function mergeOptions(parent, child) {
    const options = {}
    for (let key in parent) {
        mergeField(key)
    }

    for (let key in child) {
        if (!parent.hasOwnProperty(key)) {
            mergeField(key)
        }
    }

    function mergeField(key) {
        if (starts[key]) {
            // 可能 只传入 一个参数
            options[key] = starts[key](parent[key], child[key])
        } else {
            options[key] = child[key]
        }
    }

    return options
}


//  nextTick 函数原理
let callbacks = []
let pending = false
let timerFunc

// 将所有 的函数都执行结束
function falshCallback() {
    while (callbacks.length) {
        const cb = callbacks.pop()
        cb()
    }
    pending = false
}

// 浏览器兼容
if (Promise) {
    timerFunc = () => { Promise.resolve().then(falshCallback) }
} else if (MutationObserver) {
    // 观察数据变化，一变化就执行
    const observe = new MutationObserver(falshCallback)
    const node = document.createTextNode(1);
    observe.observe(node, { characterData: true });
    timerFunc = () => {
        node.textContent = 2
    }
} else if (setTimeout) {
    timerFunc = () => {
        setTimeout(falshCallback)
    }
}

export function nextTick(cb) {
    // 添加
    callbacks.push(cb)
    if (!pending) {
        // 异步处理
        timerFunc()
        pending = true
    }
}